﻿/*********************************************************************************/
/**    Pattern Preset Color Extractor                                           **/
/**    Copyright (C) 2012  Anja Knackstedt                                      **/
/**                                                                             **/
/**    This program is free software: you can redistribute it and/or modify     **/
/**    it under the terms of the GNU General Public License as published by     **/
/**    the Free Software Foundation, either version 3 of the License, or        **/
/**    (at your option) any later version.                                      **/
/**                                                                             **/
/**    This program is distributed in the hope that it will be useful,          **/
/**    but WITHOUT ANY WARRANTY; without even the implied warranty of           **/
/**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            **/
/**    GNU General Public License for more details.                             **/
/**                                                                             **/
/**    You should have received a copy of the GNU General Public License        **/
/**    along with this program.  If not, see <http://www.gnu.org/licenses/>.    **/
/**                                                                             **/
/*********************************************************************************/

using System;
using System.Xml;
using System.Drawing;
using System.Globalization;

namespace PatternPresetColorExtractor
{
    /// <summary>
    /// decodes xml of a Pattern or a PatternPackage
    /// Pattern: retrieves the color values
    /// PatternPackage: retrieves package Length and Offset
    /// </summary>
    class XmlDecoder
    {
        #region xml element strings

        private static string xmlVariablesNodeName      = "variables";
        private static string xmlParamNodeName          = "param";
        private static string xmlTypeAttributName       = "type";
        private static string xmlNameAttributName       = "name";
        private static string xmlDefaultAttributName    = "default";

        private static string xmlPackageIdNodeName      = "PackageId";
        private static string xmlPackageFileNodeName    = "PackagedFile";

        private static string xmlPackageGuidNodeName    = "Guid";
        private static string xmlPackageLengthNodeName  = "Length";
        private static string xmlPackageOffsetNodeName  = "Offset";

        private static string xmlComplateAttributCategory = "category";
        private static string xmlComplateAttributType = "type";
        private static string xmlComplateAttributSurfaceCategory = "surfaceMaterial";

        private static string xmlManifestTitelNodeName = "packagetitle";

        #endregion

        #region methods

        /// <summary>
        /// decodes a pattern
        /// </summary>
        /// <param name="pattern"></param>
        public void decode(Pattern pattern)
        {
           
           decodePatternXml(pattern);
           decodeManifestXml(pattern);
        }

        /// <summary>
        /// reads title from the manifest
        /// </summary>
        /// <param name="pattern"></param>
        private void decodeManifestXml(Pattern pattern)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(pattern.Manifest);

            XmlNodeList titleElements = xmlDocument.GetElementsByTagName(xmlManifestTitelNodeName);
            if (titleElements.Count > 0)
            {
                pattern.Title = titleElements[0].InnerText;
            }
            
        }

        /// <summary>
        /// decodes color values from pattern resource xml
        /// </summary>
        /// <param name="pattern"></param>
        private void decodePatternXml(Pattern pattern)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(pattern.Xml);

            XmlNode complate = xmlDocument.DocumentElement;

            Color[] colors = new Color[4];

            for (int i = 0; i < colors.Length; i++)
            {
                colors[i] = Color.Empty;
            }

            //search for attributes category, type, surface Material
            XmlAttributeCollection complateAttributes = complate.Attributes;

            foreach (XmlAttribute attribute in complateAttributes)
            {
                if (attribute.Name == xmlComplateAttributCategory)
                {
                    pattern.Category = attribute.Value;
                }
                else if (attribute.Name == xmlComplateAttributType)
                {
                    pattern.Type = attribute.Value;
                }
                else if (attribute.Name == xmlComplateAttributSurfaceCategory)
                {
                    pattern.SurfaceMaterial = attribute.Value;
                }
            }

            //search for the param nodes 
            foreach (XmlNode node in complate.ChildNodes)
            {
                if (node.Name == xmlVariablesNodeName)
                {
                    foreach (XmlNode subnode in node.ChildNodes)
                    {
                        if (subnode.Name == xmlParamNodeName)
                        {
                            //get the color params
                            if (subnode.Attributes[xmlTypeAttributName].Value == "color")
                            {
                                string colorName = subnode.Attributes[xmlNameAttributName].Value;
                                string colorValues = subnode.Attributes[xmlDefaultAttributName].Value;

                                string[] splitValues = colorValues.Split(',');

                                int colorID = Convert.ToInt32(colorName.Substring(colorName.Length - 1));


                                int alpha = (int)Math.Round(Convert.ToDouble(splitValues[3], CultureInfo.InvariantCulture.NumberFormat) * 255, 0, MidpointRounding.AwayFromZero);
                                int red = (int)Math.Round(Convert.ToDouble(splitValues[0], CultureInfo.InvariantCulture.NumberFormat) * 255, 0, MidpointRounding.AwayFromZero);
                                int green = (int)Math.Round(Convert.ToDouble(splitValues[1], CultureInfo.InvariantCulture.NumberFormat) * 255, 0, MidpointRounding.AwayFromZero);
                                int blue = (int)Math.Round(Convert.ToDouble(splitValues[2], CultureInfo.InvariantCulture.NumberFormat) * 255, 0, MidpointRounding.AwayFromZero);

                                Color color = System.Drawing.Color.FromArgb(alpha, red, green, blue);

                                colors[colorID] = color;
                            }
                        }
                    }
                }
            }

            pattern.Colors = colors;
        }

        /// <summary>
        /// decodes main package offset and length from sims3pack xml
        /// </summary>
        /// <param name="patternPackage"></param>
        public void decode(PatternPackage patternPackage)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(patternPackage.Xml);

            XmlNode sims3packNode = xmlDocument.DocumentElement;

            string packageID = "";
            string guid = "";
            int length = -1;
            int offset = -1;

            foreach (XmlNode sims3packChildNode in sims3packNode.ChildNodes)
            {
                if (sims3packChildNode.Name == xmlPackageIdNodeName)
                {
                    packageID = sims3packChildNode.InnerText;
                }
                else if (sims3packChildNode.Name == xmlPackageFileNodeName)
                {
                    foreach (XmlNode packageNode in sims3packChildNode.ChildNodes)
                    {
                        if (packageNode.Name == xmlPackageGuidNodeName)
                        {
                            guid = packageNode.InnerText;
                        }
                        else if (packageNode.Name == xmlPackageLengthNodeName)
                        {
                            length = Convert.ToInt32(packageNode.InnerText);
                        }
                        else if (packageNode.Name == xmlPackageOffsetNodeName)
                        {
                            offset = Convert.ToInt32(packageNode.InnerText);
                        }
                    }

                    //if package is main package get length and offset
                    if (packageID.ToLower() == guid.ToLower())
                    {
                        patternPackage.Length = length;
                        patternPackage.Offset = offset;
                    }
                    
                }
            }
        }

        #endregion
    }
}
